///******************** NG.Respate(C)  **********************************
//* 产品名称: Respate 科技
//* 程序作者: 雷帕特公司(南宫子萍)
//* 程序版本: V1.1														   
//* 编制日期: 2019/1/29
//* 功能描述: DHT11驱动
//* QQ:	2085827949
//**********************************************************************/
#include "DHT11.h"


#if 0	//适用于能精确产生微秒的51单片机

/*******************************************************************************
* 函数名			: DHT11_Start
* 函数功能		: DHT11 发送起始信号
* 输入			: None.
* 输出         	: None.
***********************************/
u8 DHT11_Start(void)	// DHT11 发送起始信号
{
	u8 timeOut = 0;		//等待超时时间
	
	DHT11_DQ=1;
	delay_us(2);
	DHT11_DQ=0;
	delay_ms(22);   //延时18ms以上
	DHT11_DQ=1;
	delay_us(2);
	while(DHT11_DQ == 1) 	//等待DHT11 拉低信号（80us）
	{
		delay_us(3);
		if(timeOut++ >= 30)	//低电平检测超时
			return 1;		//未检测到DHT11
	}
	return 0;				//检测到DHT11
}


/*******************************************************************************
* 函数名			: DHT11_RxByte
* 函数功能		: DHT11 接收1字节
* 输入			: 无
* 返回			: dat：当前字节值
*******************************************************************************/
u8 DHT11_RxByte(void)	//接收一个字节
{
	u8 i,dat=0;
	u8 timeOut = 0;		//等待超时时间
	for(i=0;i<8;i++)    //从高到低依次接收8位数据  	数据判定规则 ： 数据0 : 50us的低电平 + 26-28us的高电平    数据1 : 50us的低电平 + 70us的高电平  
	{  
      timeOut = 20;
	  while(DHT11_DQ == 0);	//等待50us低电平过去
	  delay_us(40);     	//延时50us，如果还为高则数据为1，否则为0 
	  dat<<=1;       		//移位使正确接收8位数据，数据为0时直接移位
		
	  if(DHT11_DQ==1)		//数据为1时，使dat加1来接收数据1
		 dat+=1;
	  while(DHT11_DQ==1&&timeOut--)	//等待数据线拉低
		delay_us(10);
	}  
    return dat;
}



/*******************************************************************************
* 函数名		: DHT11_GetData
* 函数功能		: DHT11 接收32bit(4字节)数据
* 输入			: 无
* 输出         	: buff 存放当前温度与湿度
* 返回			: 0：成功  其他：错误
*******************************************************************************/
u8 DHT11_GetData(u8 buff[])      //接收40位的数据
{
	u8 Rectify  = 0;//校正位
    u8 HUM_H = 0;	//温度 高字节
	u8 HUM_L = 0;	//温度 低字节
	u8 TEM_H = 0;	//湿度 高字节
	u8 TEM_L = 0;	//湿度 低字节
	u8 timeOut = 16;	//等待超时时间
//	u8 temp[4]={0};	//数据临时储存 buff可以不用清0
	u8 i = 0;
    if(DHT11_Start() == 0)		//检测到DHT11
	{
        while(DHT11_DQ == 0&&timeOut--)   	//等待拉高     
        delay_us(10);  	//等待超时时间
		if(timeOut==0)
			return 3;	//等待超时
		delay_us(90);  			//拉高后延时80us
        HUM_H=DHT11_RxByte();   //接收湿度高八位  
        HUM_L=DHT11_RxByte();   //接收湿度低八位 
		
        TEM_H=DHT11_RxByte();   //接收温度高八位  
        TEM_L=DHT11_RxByte();   //接收温度低八位
		
        Rectify = DHT11_RxByte();//接收校正位
        delay_us(25);    		 //结束

        if((HUM_H+HUM_L+TEM_H+TEM_L)==Rectify) //校验数据的正确性
        {
            buff[0] = (HUM_H/10);	//湿度整数部分
			buff[1] = (HUM_L%10);	//湿度小数部分
            buff[2] = (TEM_H/10);	//温度整数部分
            buff[3] = (TEM_L%10);	//温度小数部分
			return 0;				//校验正确 温湿度读取成功
        } 
    }
	else	//未检测到DHT11	
	{	
		Usart_Int2Str(1);
		return 1;	//未检测到DHT11
	}
	
	Usart_Int2Str(2);
	return 2;			//校验错误 温湿度读取失败
}
#endif
















#if 1	//适用于系统频率较低 不能产生精确的微秒级单片机	//@11.0592MHz 50us


/*******************************************************************************
* 函数名			: DHT11_Start
* 函数功能		: DHT11 发送起始信号
* 输入			: None.
* 输出         	: None.
***********************************/

u8 DHT11_Start(void)	// DHT11 发送起始信号
{
	u8 timeOut = 0;		//等待超时时间
	
	timeOut=200;
	DHT11_DQ=1;
	DHT11_DQ=0;		//开始拉低信号线 发送开始信号
	delay_ms(40);	//保证延时大于18ms
	DHT11_DQ=1;		//拉高信号线 开始接收响应信号
	while(DHT11_DQ&&timeOut)timeOut--;//开始检查是否有响应信号(80us 高电平)	
	if(timeOut==0)	//DHT11响应失败
	{
		return 1;
	}
	return 0;		//检测到DHT11
}


/*******************************************************************************
* 函数名			: DHT11_RxByte
* 函数功能		: DHT11 接收1字节
* 输入			: 无
* 返回			: dat：当前字节值
*******************************************************************************/
u8 DHT11_RxByte(void)	//接收一个字节
{
	u8 Temp = 0;
	u8 i = 0;
	u8 timeOut=200;
	
	for(i=0;i<8;i++)	//到了这里就说明要接收数据了
	{  
		Temp<<=1;
		timeOut=200;
		while(DHT11_DQ&&timeOut--);
		
		timeOut=200;
		while((!DHT11_DQ)&&timeOut--);
		
		timeOut = 4;
		while(timeOut--);
		
		if(DHT11_DQ)//说明是数据1
			Temp|=0x01;					
	}
	return Temp;
}



/*******************************************************************************
* 函数名			: DHT11_GetData
* 函数功能		: DHT11 接收32bit(4字节)数据
* 输入			: 无
* 输出         	: buff 存放当前温度与湿度 temp:温度值(范围:0~50°)  humi:湿度值(范围:20%~90%)
* 返回			: 0：成功  其他：错误
*******************************************************************************/
u8 DHT11_GetData(u8 buff[])      //接收40位的数据
{
	u8 timeOut=200;
	u8 Rectify  = 0;//校正位
    u8 HUM_H = 0;	//温度 高字节
	u8 HUM_L = 0;	//温度 低字节
	u8 TEM_H = 0;	//湿度 高字节
	u8 TEM_L = 0;	//湿度 低字节
	
	DHT11_DQ=1;
	DHT11_DQ=0;//开始拉低信号线 发送开始信号
	delay_ms(40);//保证延时大于18ms
	DHT11_DQ=1;//拉高信号线 开始接收响应信号
	
	while(DHT11_DQ&&timeOut)timeOut--;	//等待响应信号	
	if(timeOut==0)						//DHT11响应失败
		return 1;

	timeOut=200;						//已经检测到响应信号
	while((!DHT11_DQ)&&timeOut)timeOut--;
	if(timeOut==0)
		return 2;
	
	HUM_H=DHT11_RxByte();   //接收湿度高八位  
	HUM_L=DHT11_RxByte();   //接收湿度低八位 
	TEM_H=DHT11_RxByte();   //接收温度高八位  
	TEM_L=DHT11_RxByte();   //接收温度低八位
	Rectify = DHT11_RxByte();//接收校正位
	
	DHT11_DQ=1;		//释放总线
	delay_us(25);   //结束
	if((HUM_H+HUM_L+TEM_H+TEM_L)==Rectify) //校验数据的正确性
	{
		buff[0] = (HUM_H);	//湿度整数部分
		buff[1] = (HUM_L);	//湿度小数部分
		buff[2] = (TEM_H);	//温度整数部分
		buff[3] = (TEM_L);	//温度小数部分
					
	} 
	return 0;	//校验正确 温湿度读取成功
}


#endif








	
















